/*
 * @Descripttion:
 * @version: v1.0
 * @Author: LiWen
 * @Date: 2022-02-23 21:02:28
 * @LastEditors: LiWen
 * @LastEditTime: 2022-03-22 17:01:11
 */
import { createWebHashHistory, createRouter, RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { deepCopyObject, hasOwnProp, travelTree } from '../common/utils/normalUtils'
import Login from '../views/login/index.vue'
import Layout from '../views/pages/index.vue'
import { appState, exitApp, showAppLoading } from '../common/manager/appManager'
import { clearPageCatch, hasRoutePermission, validToken } from '../common/manager/PermissionManager'
import Component404 from '../views/error/404.vue'
import routeConst from './routeConst'
import { validSystemMenuIsSelf } from '../common/utils/OldSysTools'


// ################################################################################ components #########################################
const pagesComponents = (import.meta as any).glob('../views/pages/**/*.vue')
const pageMap:any = {}

/**
 * 初始化路由组件
 */
const initChartLibs = () => {
    for (const page in pagesComponents) { // 以包名为key
        const path = page.replace('../views/pages/', '').replace('.vue', '')
        pageMap[path] = pagesComponents[page]
    }
}

// ################################################################################ static path #########################################

/**
 * 静态路由列表
 */
const constantRoutes = [
        {
            path: '/:pathMatch(.*)*',
            component: Component404
        },
        {
            path: routeConst.ERROR_404,
            component: Component404
        },
        {
            path: routeConst.BLANK,
            component: () => import(/* webpackChunkName: "401" */ '../views/error/Blank.vue')
        },
        {
            path: routeConst.ERROR_401,
            component: () => import(/* webpackChunkName: "401" */ '../views/error/401.vue')
        },
        {
            path: routeConst.ERROR_403,
            component: () => import(/* webpackChunkName: "403" */ '../views/error/403.vue')
        },
        {
            path: routeConst.LOGIN,
            name: routeConst.LOGIN,
            component: Login
        }
    ]

/**
 *
 */
export const excludePath = []

// ################################################################################ 路由对象 #########################################
NProgress.configure({ showSpinner: false })
export const router = createRouter({
    history: createWebHashHistory(),
    routes: constantRoutes,
    scrollBehavior(to:any, from:any, savedPosition:any) {
        if (savedPosition) {
            return savedPosition
        } else {
            return { top: 0 }
        }
    }
})


/**
 * 创建动态路由
 * @param routes [{component:"",meta:{title:"",icon:""},path:"",redirect:"",isCache:"",isFrame:"",framePath:"", id:"",parentId:""}]
 * @param routes
 * @param copy
 */
export function initMainRoutes(routes:any[], copy = false) {
    if (copy)routes = deepCopyObject(routes || [])
    const mainPage:any = {
        path: routeConst.MAIN,
        name: routeConst.MAIN,
        component: Layout,
        layout: true,
        children: []
    }
    const catchPath = []// 记住这里把父路径的缓存一起加上 后面改temp????
    const menuMap:any = {}
    // 初始化组件列表
    initChartLibs()
    // 本系统菜单
    let menus = []
    const otherMenus = []
    for (const item of routes) {
        if (validSystemMenuIsSelf(item))menus.push(item)
        else otherMenus.push(item)
    }
    // 固定第一层去掉
    if (menus.length > 0 && menus[0].path === mainPage.path) menus = menus[0].children || []
    // 本系统菜单
    travelTree(menus, (item:any, pItem:any) => {
        // 处理基本属性
        handlerMenuAtt(item, pItem, mainPage.path)
        let component = null
        // 路由视图
        if (item.component) component = initRouteComponent(item, pItem)
        else if (item.isFrame === '0' || item.isFrame === true)component = initIFrameComponent(item, pItem)
        else item._route = (pItem && pItem._route) ? pItem._route : mainPage
        if (component) {
            const route = {
                name: item.name,
                path: item.path,
                component,
                meta: { ...item, framePath: item.framePath, isCatch: Boolean(item.isCatch) },
                children: []
            }
            item._route = route
            if (!pItem) mainPage.children.push(route)
            else pItem._route.children.push(route)
            // 缓存路由
            if (item.isCache)catchPath.push(route.name)
        }
        item.key = item.path
        // 做一个扁平化好查找
        menuMap[item.path] = item
        menuMap['_name_' + item.name] = item
    })
    router.addRoute(mainPage)
    return {
        menus,
        menuMap,
        defaultRoute: getRouteLefDefault(mainPage).path
    }
}

/**
 * 导航模式 把本系统
 * @param routes
 */
export function initNaveMenu(routes:any[]) {
    for (const item of routes) {
        if (validSystemMenuIsSelf(item)) handlerMenuAtt(item, null, routeConst.MAIN)
    }
    return routes
}

/**
 * 获取路由 可访问 叶子
 * @param route
 */
export function getRouteLefDefault(route:any):any {
    if (!route.children || route.children.length === 0) return route
    return getRouteLefDefault(route.children[0])
}

/**
 * 初始化路由组件
 * @param item
 * @param pItem
 */
function initRouteComponent(item:any, pItem:any) {
    let component = Component404
    // 老版配置兼容
    if (item.component === 'Layout') item.component = item.name + '/index'
    else if (pItem && item.component.indexOf('pages/') === 0 && item.component.indexOf('/index') > 0) {
        item.component = pItem.name + '/' + item.name + '/index'
    }
    if (item.component) {
        if (hasOwnProp(pageMap, item.component)) component = pageMap[item.component]
        else if (hasOwnProp(pageMap, item.component + '/index')) component = pageMap[item.component + '/index']
    }
    return component
}

/**
 * 嵌入路由 是嵌入导航 还是 直接跳转得有参数支撑 temp?????
 * @param item
 * @param pItem
 */
function initIFrameComponent(item:any, pItem:any) {

}

/**
 * 解析菜单基本属性
 * @param item
 * @param pItem
 * @param rootPath
 * @param pathAtt
 */
function handlerMenuAtt(item:any, pItem:any, rootPath:string, pathAtt = 'path') {
    item.path = item.path || ''
    item.name = item.name || ''
    item.path = (pItem ? pItem.path : rootPath) + (item.path.indexOf('/') === 0 ? item.path : ('/' + item.path))
    item.openPath = pItem ? [...pItem.openPath, pItem.path] : []
    item.title = item.meta.title
    item.icon = getRouteIcon(item)
    return item
}

// ----------------------------------------------------------------------- icon menu ----------------------------------------

/**
 * 菜单默认图标
 */
const MENU_ICON_MAP:any = {
    home:"home",
    system: 'fenlei',
    online: 'fenlei',
    page2: 'fenlei',
    page3: 'fenlei'
}
/**
 * 默认固定图标
 * @param path
 */
function getRouteIcon(item:any) {
    if (item.meta.icon) return { value: item.meta.icon, icon: item.meta.icon, isSvg: true }
    const name = item.name.toLocaleLowerCase()
    const icon = hasOwnProp(MENU_ICON_MAP, name) ? MENU_ICON_MAP[name] : ''
    return { value: icon, icon, isSvg: false }
}


// ################################################################################ defined export #########################################
/**
 * params 只做内存级存储 不和路由配置参合了
 */
const paramsCatch:any = {}
/**
 * 业务跳转使用
 */
export async function changeRoute(path:string, query:any = {}, replace = false, params:any = null) {
    if (!hasRoutePermission(path)) {
        postMessage('没有权限！')
        console.log('==============changeRoute======没有权限==============>>>>', path)
        return null
    }
    const result = await changeRouteExecute(path, query, replace, params)
    return result
}

/**
 * 切换主系统菜单
 * @param path
 */
export function changeMainRoute(path:string) {
    if (!hasOwnProp(appState.menuMap, path)) return
    const menuData = appState.menuMap[path]
    const route = getRouteLefDefault(menuData)
    // 如果有叶子菜单切换 否者 切换主路由  后面可以把默认跳转逻辑加上 temp????
    if (route)changeRouteExecute(route.path)
    else changeRouteExecute(path)
}

/**
 * 内部调用使用
 * @param path
 * @param query
 * @param replace
 * @param params
 */
export function changeRouteExecute(path:any, query:any = {}, replace = false, params:any = null):Promise<any> {
    let route:any = path
    if (typeof path === 'string') {
        route = { path, query }
        paramsCatch[path] = params || null
    }
    if (replace) return router.replace(route)
    return router.push(route)
}

/**
 *
 * @param route
 */
export function getRouteParams(route:any) {
    if (!route) return null
    if (typeof route === 'string' && hasOwnProp(paramsCatch, route)) return paramsCatch[route]
    else if (route && hasOwnProp(route, 'path') && hasOwnProp(paramsCatch, route.path)) return paramsCatch[route.path]
    return null
}

/**
 * 按照缓存路由初始化
 * @param defaultPath
 */
export function resetDefaultRoute(catchRoute = '') {
    if (catchRoute && !isStaticPath(catchRoute)) changeRouteExecute(catchRoute, {}, true)
    else changeRouteExecute(appState.defaultRoute, {}, true)
}

/**
 * 返回重新登录
 */
export function changeToLogin() {
    exitApp()
}

/**
 * 固定路由
 * @param path
 */
export function isStaticPath(path:string) {
    return path.indexOf(routeConst.ERROR) === 0 || path === routeConst.LOGIN
}

/**
 * 设置标签页标题
 * @param title
 */
export function setDocumentTitle(title:any) {
    document.title = title || appState.name
}

// ################################################################################ 路由卫士 #########################################

/**
 * 普通模式路由守卫
 * @param to
 * @param from
 * @param next
 */
const commonBeforeEach = (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
    // 加载状态
    NProgress.start()
    showAppLoading(true)
    // 设置标题
    to.meta.title && setDocumentTitle(to.meta.title)

    // 如果不是嵌入模式默认跳转到登录否则跳转到首页
    if (to.path === '/') {
        next(appState.userInit ? appState.defaultRoute : routeConst.LOGIN)
        return
    }

    // 如果是登录和错误界面直接跳转
    if (to.path.indexOf(routeConst.ERROR) === 0) {
        next()
        return
    }
    if (to.path === routeConst.LOGIN) {
        clearPageCatch()
        next()
        return
    }

    // 验证token
    const flag = validToken()
    // 验证不通过 跳转登录页面
    if (!flag) {
        clearPageCatch()
        next(routeConst.LOGIN)
        return
    }

    // 如果有token而且当前页面已经获得用户信息直接跳转
    if (appState.userInit || appState.debugMode) {
        next()
        return
    }
    // 否则直接跳转登录页面
    clearPageCatch()
    next(routeConst.LOGIN)
}

/**
 * 嵌入模式路由守卫
 * @param to
 * @param from
 * @param next
 */
const embedBeforeEach = (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
    // 加载状态
    showAppLoading(true)
    // 设置标题
    to.meta.title && setDocumentTitle(to.meta.title)

    // 嵌入模式默认跳转到空白页面 否则跳转到设置的默认路由
    if (to.path === '/') {
        next(appState.userInit ? appState.defaultRoute : routeConst.BLANK)
        return
    }
    // 如果是登录和错误界面直接跳转
    if (to.path.indexOf(routeConst.ERROR) === 0 || to.path === routeConst.BLANK) {
        next()
        return
    }
    if (to.path === routeConst.LOGIN) {
        clearPageCatch()
        next()
        return
    }

    // 验证token
    const flag = validToken()
    // 验证不通过 跳转401页面
    if (!flag) {
        clearPageCatch()
        next(routeConst.ERROR_403)
        return
    }

    // 如果有token而且当前页面已经获得用户信息直接跳转
    if (appState.userInit || appState.debugMode) {
        next()
        return
    }
    // 否则直接跳转无权限页面
    clearPageCatch()
    next(routeConst.BLANK)
}


/**
 * 路由拦截
 */
router.beforeEach((to:any, _from, next) => {
    if (appState.embed)embedBeforeEach(to, _from, next)
    else commonBeforeEach(to, _from, next)
})

router.afterEach((to:any) => {
    NProgress.done()
    showAppLoading(false)
})

export { routeConst }

